package classFanshe;

import com.sun.org.slf4j.internal.Logger;
import domain.Student;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.logging.LogManager;

public class Demo {
    public static void main(String[] args) throws Exception {
        // method1();

        // method2();

        // method3();

        // method4();

        // method5();

        // method6();

        // method7();

        // method8();

        // method9();

        // method10();

        // method11();

        // method12();

        // mrthod13();

        // method14();


    }

    private static void method14() throws DocumentException {
        // 1.获取一个解析器对象
        SAXReader saxReader = new SAXReader();
        // 2.利用解析器把xml文件加载到内存中并返回一个文档对象
        Document document = saxReader.read(new File("xml\\myFirstXml.xml"));
        // 3.获取根标签
        Element rootElement = document.getRootElement();
        // 4.通过根标签获取student标签
        // elements():可以获取调用者所有的子标签，会把子标签放到一个集合中返回
        // elements(String s):获取指定所有子标签
        List<Element> studentElements = rootElement.elements("student");


        // 5.遍历集合得到每一个student标签
        for (Element element : studentElements) {
            // attribute()方法获取属性
            Attribute idAttribute = element.attribute("id");
            String id = idAttribute.getValue();

            // 获取name标签
            // element("标签名")：获取指定的子标签
            Element nameElement = element.element("name");
            // 获取这个标签的标签体中的内容
            String name = nameElement.getText();

            Element ageElement = element.element("age");
            String age = ageElement.getText();

            System.out.println(id + name + age);
        }
    }

    private static void mrthod13() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        // 获取Class对象
        Class<?> aClass = Class.forName("domain.Student");

        Method function = aClass.getDeclaredMethod("function", String.class);

        function.setAccessible(true); // 暴力反射

        // 以下则是调用获取到的方法的过程
        Student stu = (Student) aClass.newInstance();
        Object zhang = function.invoke(stu, "zhang");

        System.out.println(zhang);
    }

    private static void method12() throws ClassNotFoundException, NoSuchMethodException {
        // 获取Class对象
        Class<?> aClass = Class.forName("domain.Student");

        // 获取指定public成员方法
        Method setName = aClass.getMethod("setName", String.class);

        // 获取指定private成员方法
        Method setSid = aClass.getDeclaredMethod("setSid", String.class);

        System.out.println(setName);
        System.out.println(setSid);
    }

    private static void method11() throws ClassNotFoundException {
        // 获取Class对象
        Class<?> aClass = Class.forName("domain.Student");

        // 获取所有成员方法
        Method[] methods = aClass.getDeclaredMethods();// 不会获取父类的方法
        for (Method method : methods) {
            System.out.println(method);
        }
    }

    private static void method10() throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {
        // 获取Class对象
        Class<?> aClass = Class.forName("domain.Student");

        // 获取Field对象
        Field birthday = aClass.getDeclaredField("birthday");

        birthday.setAccessible(true); // 暴力反射

        // 利用Field中的set方法进行赋值
        Student stu = (Student) aClass.newInstance();
        birthday.set(stu, "2020-11-11");
        System.out.println(stu);

        // 利用Field中的get方法获取属性值
        Object o = birthday.get(stu);
        System.out.println(o);
    }

    private static void method9() throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {
        // 获取Class对象
        Class<?> aClass = Class.forName("domain.Student");

        // 获取Field对象
        Field name = aClass.getField("name");

        // 利用Field中的set方法进行赋值
        Student stu = (Student) aClass.newInstance();
        name.set(stu, "zhangsan");
        System.out.println(stu);

        // 利用Field中的get方法获取属性值
        Object o = name.get(stu);
        System.out.println(o);
    }

    private static void method8() throws ClassNotFoundException, NoSuchFieldException {
        // 获取Class对象
        Class<?> aClass = Class.forName("domain.Student");
        // 获取指定存在的私有成员变量
        Field birthday = aClass.getDeclaredField("birthday");
        System.out.println(birthday);
    }

    private static void method7() throws ClassNotFoundException {
        // 获取Class对象
        Class<?> aClass = Class.forName("domain.Student");
        // 获取所有成员变量
        Field[] fields = aClass.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field);
        }
    }

    private static void method6() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, java.lang.reflect.InvocationTargetException {
        // 获取Class对象
        Class<?> aClass = Class.forName("domain.Student");
        // 获取构造方法对象
        Constructor<?> constructor = aClass.getDeclaredConstructor(String.class, int.class);

        // 若要使用反射强行使用private修饰的构造方法创建对象
        // 需要调用以下方法
        constructor.setAccessible(true); // 暴力反射

        // 利用newInstance方法创建对象
        Student zhangsan = (Student) constructor.newInstance("zhangsan", 23);
        System.out.println(zhangsan);
    }

    private static void method5() throws ClassNotFoundException, NoSuchMethodException {
        // 获取Class对象
        Class<?> aClass = Class.forName("domain.Student");
        //Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)返回一个 Constructor对象，该对象反映 Constructor对象表示的类或接口的指定 类函数。
        // 该方法可以获取类中任何权限的方法
        Constructor<?> declaredConstructor1 = aClass.getDeclaredConstructor(String.class, int.class);
        System.out.println(declaredConstructor1);
    }

    private static void method4() throws ClassNotFoundException, NoSuchMethodException {
        // 获取Class对象
        Class<?> aClass = Class.forName("domain.Student");
        //Constructor<T> getConstructor(Class<?>... parameterTypes)返回一个 Constructor对象，该对象反映 Constructor对象表示的类的指定的公共 类函数。
        // 注意：小括号中必须跟方法的形参保持一致，并且方法必须是public的
        Constructor<?> constructor1 = aClass.getConstructor();
        System.out.println(constructor1);

        Constructor<?> constructor2 = aClass.getConstructor(String.class, int.class);
        System.out.println(constructor2);
    }

    private static void method3() throws ClassNotFoundException {
        // 获取Class对象
        Class<?> aClass = Class.forName("domain.Student");
        //Constructor<?>[] getDeclaredConstructors()返回一个反映 Constructor对象表示的类声明的所有 Constructor对象的数组 类 。
        Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
    }

    private static void method2() throws ClassNotFoundException {
        // 获取Class对象
        Class<?> aClass = Class.forName("domain.Student");
        //Constructor<?>[] getConstructors()返回包含一个数组 Constructor对象反射由此表示的类的所有公共构造 类对象。
        Constructor<?>[] constructors = aClass.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
        }
    }

    private static void method1() throws ClassNotFoundException {
        // 1.利用Class中的静态方法forName(String 全类名)
        Class<?> aClass = Class.forName("domain.Student");
        System.out.println(aClass);

        // 2.通过Class属性来获取
        Class<?> bClass = Student.class;
        System.out.println(bClass);

        // 3.通过对象的getClass方法来获取对象，该方法是定义在Object中的
        Student s = new Student();
        Class<?> cClass = s.getClass();
        System.out.println(cClass);

        System.out.println(aClass == bClass);
        System.out.println(bClass == cClass);
    }
}
